package cn.joeg.app.web.core.service;

import cn.joeg.app.web.core.interceptor.WidgetAuthInterceptor;
import cn.joeg.app.web.core.def.BasicWidgetAdapter;
import cn.joeg.app.web.core.interceptor.WidgetDataFetchInterceptor;
import cn.joeg.app.web.core.vo.WidgetDataReq;
import cn.joeg.app.web.core.vo.WidgetDataResp;
import cn.joeg.app.web.items.ItemPackage;
import com.ecfront.dew.common.ClassScanHelper;
import com.ecfront.dew.common.JsonHelper;
import com.ecfront.dew.common.Resp;
import com.ecfront.dew.common.interceptor.DewInterceptRespBody;
import com.ecfront.dew.common.interceptor.DewInterceptorProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;


import javax.annotation.PostConstruct;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

@Service
public class WidgetService {

    private static final Logger logger = LoggerFactory.getLogger(WidgetService.class);

    public static final Map<String, BasicWidgetAdapter> WIDGET_ITEMS = new HashMap<>();

    //    @Autowired
//    private WidgetDefInterceptor widgetDefInterceptor;
//    @Autowired
//    private WidgetCacheInterceptor widgetCacheInterceptor;
//    @Autowired
//    private WidgetOptLogInterceptor widgetOptLogInterceptor;
    @Autowired
    private WidgetAuthInterceptor widgetAuthInterceptor;
//    @Autowired
//    private WidgetKeyDataInterceptor widgetKeyDataInterceptor;

    @Autowired
    private ApplicationContext applicationContext;

    @PostConstruct
    public void init() throws IOException, ClassNotFoundException {
        initInterceptors();
        initWidgetItems();
    }

    private void initInterceptors() {
        // 添加到拦截器栈
        DewInterceptorProcessor.register(WidgetDataFetchInterceptor.CATEGORY, widgetAuthInterceptor);
//        DewInterceptorProcessor.register(WidgetDataFetchInterceptor.CATEGORY, widgetDefInterceptor);
        // DewInterceptorProcessor.register(WidgetDataFetchInterceptor.CATEGORY, widgetOptLogInterceptor);
//        DewInterceptorProcessor.register(WidgetDataFetchInterceptor.CATEGORY, widgetCacheInterceptor);
        // DewInterceptorProcessor.register(WidgetDataFetchInterceptor.CATEGORY, widgetKeyDataInterceptor);
        // DewInterceptorProcessor.register(WidgetDataFetchInterceptor.CATEGORY, widgetKeyDataInterceptor);
    }

    private void initWidgetItems() throws IOException, ClassNotFoundException {
        ClassScanHelper.scan(
                ItemPackage.class.getName().substring(0, ItemPackage.class.getName().lastIndexOf(".")),
                null, new HashSet<String>() {{
                    add("WidgetAdapter");
                }}).stream().forEach(clazz -> {
            BasicWidgetAdapter adapter = (BasicWidgetAdapter) applicationContext.getBean(clazz);
            WIDGET_ITEMS.put(adapter.getCode(), adapter);
        });
    }

    public Resp<WidgetDataResp> getDataByCode(String widgetCode, WidgetDataReq widgetDataReq) {
        widgetDataReq.setWidgetCode(widgetCode);
        Resp<DewInterceptRespBody<WidgetDataReq>> result = DewInterceptorProcessor.process(WidgetDataFetchInterceptor.CATEGORY, widgetDataReq, new HashMap<>(), (obj, context) -> {
//            Object cacheData = context.getOrDefault(WidgetCacheInterceptor.CACHE_DATA_CONTEXT, null);
            Object cacheData = context.getOrDefault("cacheData", null);
            if (cacheData != null) {
                //hit cache
                obj.setWidgetDataResp(Resp.success(JsonHelper.toObject(cacheData, WidgetDataResp.class)));
                return Resp.success(DewInterceptRespBody.build(obj, context));
            } else {
                BasicWidgetAdapter adapter = WIDGET_ITEMS.get(widgetCode);
                if (adapter == null) {
                    return Resp.notFound(String.format("Code[%s]不存在", obj.getWidgetCode()));
                }
                try {

                    // Date time = new Date();

                    Resp<WidgetDataResp> resultR = adapter.dispatch(widgetDataReq);

                    /*logger.info("Widget Service, code : {}; method: {}; args: {}; use time: {} ms!",
                            widgetDataReq.getWidgetCode(), widgetDataReq.getWidgetMethod(),
                            JsonHelper.toJsonString(widgetDataReq.getArgs()), new Date().getTime() - time.getTime());*/

                    if (resultR.ok()) {
                        obj.setWidgetDataResp(resultR);
                        return Resp.success(DewInterceptRespBody.build(obj, context));
                    } else {
                        return Resp.customFail(resultR.getCode(), resultR.getMessage());
                    }
                } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                    logger.error("[Widget] execute error:{}", e.getMessage(), e);
                    return Resp.serverError(e.getMessage());
                }
            }
        });
        if (result.ok()) {
            return result.getBody().getObj().getWidgetDataResp();
        } else {
            return Resp.customFail(result.getCode(), result.getMessage());
        }
    }


}
